\documentstyle[times,fullpage]{article}
\newcommand{\mae}{{\bf MAEstro\ }}
\title {Video Object --- A Library for Controlling Video Devices}
\author{Wee Lee Lim\\
George D. Drapeau\\
\mae Project\\
Stanford University\\
maestro@sioux.stanford.edu}
\begin{document}

\begin{titlepage}
\maketitle
\end{titlepage}

\tableofcontents

\newpage

\section{Introduction}

For a single application to provide support for a variety of
computer-controlled videodisc and videotape players, the application
needs to include serial-line drivers for a potentially large number of
those devices.  For this purpose, we have created a generic "Video
Object" that supports features common to a number of video devices.

The purpose of this file is to instruct application programmers how to
use the Video Object library in their own applications, and to provide
help in adding new devices to the library.

If you find this object useful and write support for players other
than those supported here, we would be grateful if you would send us a
copy of your source code so that we can add your driver to the
publicly distributed VideoObject.

We hope that you find this code useful in your applications.  If you
have any comments, questions, suggestions, or source code you would
like to add, please send mail to {\tt maestro@sioux.stanford.edu}.


\section{Objectives}
The Video Library was created with the following objectives :

\begin{enumerate}
\item To allow programmers to write applications that support a variety
of video devices (such as videodisc and videotape players) without
having to write device-specific code. The application program calls a
generic {\tt Dev<Function>} regardless of what device is being used, and
the video library is able to call the correct {\tt <Function>} for the
particular device currently being used.

\item To allow programmers to be able to easily add on to the suite of 
device drivers currently available.
\end{enumerate}

  
\section{Definition of the Video Object}

The Video Library consists of device-specific code to support a number
of video devices.  A generic "object" is provided to the application
programmer; this structure contains pointers to functions that represent
the device specific routines for common actions such as 'play', 'pause',
'stop', 'search', etc.  In addition to these function pointers, the
object contains information about the currently-used video device (such
as the serial line used for communication with the device, the serial
line attributes for the device, its performance characteristics, and so
on). This information (device 'configuration') is stored in the data
structure called {\tt Config}, which is stored as part of the Video
Object.

This section will describe the following components of the Video Object
in detail:

\begin{itemize}
\item{Config ---} Data structure containing device-specific serial line and
performance attributes

\item{Video Functions ---} The various functions supported by the Video
Object and their semantics.

\end{itemize}

This section ends with a note on status codes, outlining the differences
between the status codes returned by the devices, and the status codes
that are returned from the Video Object to the application.


\subsection{The {\tt Config} Structure --- Video Device Configuration}

The {\tt Config} data structure stores the configuration of a particular
video device, and is defined as follows:

\begin{verbatim}
        typedef struct _Config 
        {       
          char modelName[MaxNameLength];
          char serialPort[15];
          int baudRate;
          int eolChar;
          int charSize;
          enum Parity parity;
          enum Boolean igParError;
          enum Boolean flowControl;
          int maxSpeed;
          int fd;
        } Config;
\end{verbatim}

The {\tt modelName} field is a String that denotes the name of the
device.  This will be the name used by the application and the library.

The {\tt serialPort} field is a String that denotes the serial port to
which the device is physically attached.  This field is likely to be
different for different machines (and users).  To let applications to
use a different value for this field easily without having to change
and recompile their code, the Video Object calls {\tt XGetDefault()}
to determine the user's default serial port to use for the device.

{\tt XGetDefault()} is called with the {\tt modelName} field as its
second argument, and {\tt serialPort} as its third argument.  Therefore
the form for storing serial port defaults as an X resource is as
follows:

\begin{verbatim}
                <modelName>.serialPort:         <serial port>
\end{verbatim}

The {\tt baudRate} field is an Integer that denotes the baud rate at which
data transfer is carried out.

The {\tt eolChar} field is an Integer that represents the ASCII value
(decimal) of the character sent by the device denoting the end of a line
and that a read() should be performed.

There are two reasons why the {\tt eolChar} field is necessary.
Firstly, this field distinguishes whether the Video Object should use
canonical input processing (the value of {\tt eolChar} is non- negative)
or non-canonical input processing (the value of {\tt eolChar} is
negative) to communicate with the device.  Canonical input processing is
used for devices that return a special character to denote the end of a
line, while non-canonical input processing is used for those devices
that do not return a special end-of-line character. [For more
information, please read the man pages on termio(4).  For an example of
a device that does canonical input processing, please look at the source
code for the Pioneer4200 Video Object (Pioneer4200Driver.c).  For an
example of a device that uses non-canonical input processing, please
look at the source code for the Sony1550 Video Object
(Sony1550Driver.c).]

Secondly, with canonical input processing, Unix recognizes a line by the
{\tt NEWLINE (ASCII LF)} character or the {\tt EOF (ASCII EOT)}
character, or two other user-specified characters.  Because different
devices have different end-of-line characters, the Video Object requires
that the device specifies explicitly its end-of-line character in this
{\tt eolChar} field.

The {\tt charSize} field is an Integer that denotes the size in bits of
a data character. Valid values can be 5, 6, 7 or 8.

The {\tt parity} field is an Enum Parity that can be either {\tt Odd},
{\tt Even}, {\tt NoParity} or {\tt Any}.

The {\tt igParError} field is an Enum Boolean that is {\tt Yes} if the
Video Object wants to ignore parity errors, and {\tt No} if the Video
Object does not want to ignore parity errors.

The {\tt flowControl} field is an Enum Boolean that is {\tt Yes} if
the flow control is desired for the device with which the Video Object
is communicating, and {\tt No} if the device does not use flow
control.

The {\tt maxSpeed} field is an Integer that denotes the maximum speed in
terms of frames/second that the device is capable of playing.

The {\tt fileDescriptor} field is an Integer that denotes the file
descriptor for the device, after the serial port connection has been
made.  Its initial value can be set to any negative number.


\subsection{Notes on Configuration Settings}

\begin{enumerate}
\item If the device does not return an end-of-line character, enter a
negative number in the {\tt eolChar} field.  It is assumed that
non-canonical input processing will be used if a negative number is
entered for the end-of-line character. See description of {\tt eolChar}
field above.

\item In non-canonical input processing, the initial values for {\tt
MIN} and {\tt TIME} are:

\begin{verbatim}
        c_cc[VMIN] = 1 and c_cc[VTIME] = 0

\end{verbatim}

This means that the read() function blocks until at least 1 character is
received.  Please read the man pages on {\tt termio(4)} for more
details.

\end{enumerate}

Here are two sample device configurations, both taken from the {\tt
videoObjects.c} file for the VideoEdit application.  The first describes
the Pioneer 4200 videodisc player.  The second configuration describes
the Sony 1550 videodisc player.  A table for ASCII values can be found
in \ref{ASCIITable}.

\begin{verbatim} 
      static Config Pioneer4200Config =                      
      {
        "Pioneer4200",                  <= modelName
        "/dev/ttya",                    <= serial Port
        4800,                   
        10,                             <= NL (ASCII 10) is the eolChar 
        8,                                              for Pioneer4200
        Even,
        Yes,
        120,
        -1
        }
        ;

      static Config Sony1550Config = 
      {
        "Sony1550",
        "/dev/ttyb",
        2400,
        -1,                             <= non-canonical input processing
        8,
        Even,
        Yes,
        90, 
        -1
        }
        ;
\end{verbatim}

\subsection{Notes on Changing the Configuration}

{\tt videoObjects.c} is the file that stores the configurations for each
device in an application (see \ref{VideoLibraryFiles}). To use the Video
Library, copy this file into your own directory and compile it with the
rest of your application.  Any changes you wish to make to video device
configurations can be made in your copy of the {\tt videoObjects.c}
file.  If you are using one of the already-supplied devices, the only
setting you might likely change is the serial port to which the device
is connected, and even this may not be necessary.

See the end of the {\tt videoObj.h} file for a list of device
configurations for currently-supported devices.

The serial line is set by {\tt SetSerialLine()}, a function supplied by
the Video Library.  {\tt SetSerialLine()} has two arguments:

\begin{enumerate}
\item Device configuration structure
\item Serial port
\end{enumerate}

Because the {\tt serialPort} field is likely to differ from machine to
machine, the Video Object chooses the serial port to connect with by
using the following procedure:

\begin{itemize}
\item Use the second argument to {\tt SetSerialLine()} if it is not NULL.
{\tt SetSerialLine()} should, in general, be called with NULL as the
second argument, because in the most cases, the serial port is not
explicitly chosen.  The second argument should be non-NULL, only when
the user specifies from within the application a particular serial
port to use.

\item Call {\tt XGetDefault()}.  If it returns a non-NULL value for the
serial port for this device, then use this value.

\item Use the value set in the configuration structure.

\end{itemize}

Thus, to change serial port without modifying any code, it is easiest
to set the default serial port in {\tt~/.Xdefaults}.

Here is an example X resource showing how a user might set the default
serial port used by the Pioneer4200 device driver:

\begin{verbatim}
   Pioneer4200.serialPort:      /dev/ttya       <= Pioneer4200 player 
                                                   is on /dev/ttya
\end{verbatim}


\subsection{Definition of Video Object Functions}
\label{DefiningVideoObjectFunctions}

The Video Object has at present 23 basic functions. Not all devices
will be able to perform all 23 functions; such devices will have NULL
function pointers for those functions they cannot perform.

The {\tt VideoObject} data structure is defined as follows:

\begin{verbatim}
        typedef struct _VideoObject 
        {
          Config* DevConfig;
          int (*DevPlayPtr) (VideoObject*);
          int (*DevPlayFromToPtr) (VideoObject*, int, int, int);
          int (*DevFastForwardPtr) (VideoObject*);
          int (*DevReversePtr) (VideoObject*);
          int (*DevCalcSpeedPtr) (VideoObject*, int, int);
          int (*DevPlayAtSpeedDirPtr) (VideoObject*, int, enum Direction);
          int (*DevStepPtr) (VideoObject*, enum Direction);
          int (*DevStillPtr) (VideoObject*);
          int (*DevStopPtr) (VideoObject*);
          int (*DevSetDefaultsPtr) (VideoObject*, int, int, int, int);
          int (*DevSetAudioPtr) (VideoObject*, int);
          int (*DevSetVideoPtr) (VideoObject*, int);
          int (*DevSetAddModePtr) (VideoObject*, int);
          int (*DevSetAddressDisplayPtr) (VideoObject*, int, int);
          int (*DevEjectPtr) (VideoObject*);
          int (*DevPowerPtr) (VideoObject*, int);
          int (*DevQueryFramePtr) (VideoObject*);
          int (*DevQueryChapterPtr) (VideoObject*);
          int (*DevQueryAudioPtr) (VideoObject*);
          int (*DevQueryVideoPtr) (VideoObject*);
          int (*DevQueryMediumPtr) (VideoObject*, char*);
          int (*DevQueryStatusPtr) (VideoObject*);
          int (*DevPingPtr) (VideoObject*);
          int (*DevRecordPtr) (VideoObject*);
          int (*DevRecordFromToPtr) (VideoObject*, int, int, int);
        } VideoObject;
\end{verbatim}

By compounding different functions, applications will be able to
achieve most of the operations commonly desired of a video device. The
following are the descriptions of what each function should do.

The functions return a status code, unless otherwise stated.  For a
description of the status codes, please see \ref{StatusAndErrorCodes}.

\begin{enumerate}
\item{\tt int (*DevPlayPtr) (VideoObject* theObject)}
 
Pointer to function that sets {\tt theObject} in 'playback' mode.

\item{\tt int (*DevPlayFromTo) (VideoObject*~theObject, int~startAddress,\\
                                int~endAddress, int~speedInFramesPerSecond)}

Pointer to function that plays a segment, from {\tt startAddress} to
{\tt endAddress}.

{\tt startAddress} and {\tt endAddress} are in terms of frames if the
player is in frame mode, and in terms of chapters if the player is in
chapter mode.

For devices that have indices rather than chapters, and only have
relative search of indices, {\tt endAddress} is used to indicate
direction. As usual, 0 is Forward, 1 is Reverse.

This function is used in 4 different ways:

\begin{enumerate}

\item{\tt startAddress == endAddress}\\
Searches to {\tt startAddress} and stills.  This is a request for a
non-blocking search; in other words, {\tt DevPlayFromTo} will send the
search command to the specific device then will return as soon as
possible (for some players, it is possible to read an acknowledge
message indicating that the command has begun execution, then a
completion message indicating that the command has completed
execution.  The VISCA protocol follows this type of communications).

\item{\tt startAddress != NULL, endAddress == NULL}\\
Searches to {\tt startAddress} and stills.  This is a request for a
blocking search; in other words, the {\tt DevPlayFromTo} function will
wait until the device completes its search before returning to the
calling application.

\item{\tt startAddress == NULL, endAddress != NULL}\\
Play from current position (no search) until {\tt endAddress} at {\tt
speedInFramesPerSecond}.

\item{\tt startAddress != endAddress,  startAddress != NULL, endAddress != NULL}\\
Play from {\tt startAddress} to {\tt endAddress} at {\tt
speedInFramesPerSecond}.  However, if {\tt startAddress} is greater than
{\tt endAddress}, then the function should return an error.

\end{enumerate}

\item{\tt int (*DevFastForwardPtr) (VideoObject* theObject)}
Pointer to function that plays forward at higher than normal
(device-dependent) speed.

It may continue to play at this speed until some other command is issued
(the usual case for VCRs), or it may return to normal playback after
scanning a certain number of frames (usually the case for videodisc
players).
   
\item{\tt int (*DevReversePtr) (VideoObject* theObject)}
Pointer to function that plays reverse at higher than normal
(device-dependent) speed.

It may continue to play at this speed until some other command is issued
(the usual case for VCRs), or it may return to normal playback after
scanning a certain number of frames (usually the case for videodisc
players).

\item{\tt int (*DevCalcSpeedPtr) (VideoObject* theObject, int inputValue,\\
                                int playMode)}
Pointer to function that returns speed (in number of frames per second)
that can be played by {\tt theObject}.

{\tt inputValue} is the actual speed in frames per second at which the
user would like to play.  {\tt playMode} is 0 for normal playback and 1
for segment play (ie playback from one address to another), since it is
found in some cases that devices are able to play at special speeds only
in normal playback mode.

\item{\tt int (*DevPlayAtSpeedDirPtr) (VideoObject* theObject,\\
                                 int speedInFramesPerSecond,\\
                                 enum Direction direction)}

Pointer to function that plays at {\tt speedInFramesPerSecond} in {\tt
direction}, where {\tt direction} can be {\tt Forward} or {\tt Reverse}.

This function should call {\tt DevCalcSpeed()} so as to obtain the
device-specific speed based on {\tt speedInFramesPerSecond}.

\item{\tt int (*DevStepPtr) (VideoObject* theObject, enum Direction
direction)}

Pointer to function that steps one frame in {\tt direction}.

\item{\tt int (*DevStillPtr) (VideoObject* theObject)}

Pointer to function that puts {\tt theObject} into {\tt still} mode,
meaning the frame is frozen, but video is not muted.

This function should be able to execute in any mode, which means that if
segment play (ie playback from one address to another) is not
interruptible by a normal pause command, an interrupt command should be
used to implement pause.

   An example of a device that cannot pause segment play is the NEC
PC-VCR.  In order to implement a pause in this mode, the driver sends
out an interrupt command before it sends out its pause command.

\item{\tt int (*DevStopPtr) (VideoObject* theObject)}

Pointer to function that puts {\tt theObject} into {\tt stop} mode, meaning that
playback is stopped and video is muted.

This function does NOT shut down the disc motor. This function should be
able to execute in any mode, which means that if segment play is not
interruptible by a normal stop command, an interrupt command should be
used to implement stop. See similar comments for {\tt DevStillPtr}, above.

\item{\tt int (*DevSetDefaultsPtr) (VideoObject* theObject, int audio,\\
                                int addressingMode,\\
                                int addressDisplayOnOff, int displayMode)}

Pointer to function that puts {\tt theObject} into desired mode when
starting it up.

\begin{itemize}

\item{\tt audio}\\
One of {\tt Mute, Left, Right, Stereo}.  Others can be assigned by the
programmer for other modes, but this might not be implemented uniformly
across all video objects!

\item{\tt addressingMode}\\
Either {\tt PlayerFrameMode = Normal} (usually means frame addressing)
or {\tt PlayerChapterMode = Indexing} (or Chapters).

\item{\tt addressDisplayOnOff}\\
Either {\tt FeatureOff} (No address display on screen) or {\tt
FeatureOn} (Address display on screen).

\item{\tt displayMode}\\
One of {\tt DisplayFrame} (Display frame address on screen), {\tt
DisplayChapter} (Display chapter on screen), or {\tt
DisplayFrameAndChapter} (Display frame and chapter on screen).

\end{itemize}

The {\tt \#define's} for these parameters are in {\tt PlayerStatus.h}.

\item{\tt int (*DevSetAudioPtr) (VideoObject* theObject, int mode)}

Pointer to function that sets audio to {\tt mode} (see definition of
{\tt DevSetDefaultsPtr}, above).

\item{\tt int (*DevSetVideoPtr) (VideoObject* theObject, int mode)}

Pointer to function that sets video to {\tt mode}, either {\tt
FeatureOn} or {\tt FeatureOff}.

\item{\tt int (*DevSetAddModePtr) (VideoObject* theObject, int mode)}

Pointer to function that sets addressing mode to {\tt mode} (see
definition of {\tt DevSetDefaultsPtr}, above).

\item{\tt int (*DevSetAddressDisplayPtr) (VideoObject* theObject, int onOff,\\
                                        int mode)}

Pointer to function that either turns on-screen address display to {\tt
on} or {\tt off} depending on value of {\tt onOff} and sets the display
to {\tt mode} (see definition of {\tt DevSetDefaultsPtr}, above).

\item{\tt int (*DevEjectPtr) (VideoObject* theObject)}

Pointer to function that ejects the medium from the player.  Returns
status code.

\item{\tt int (*DevPowerPtr) (VideoObject* theObject, int mode)}

Pointer to function that turns power either on or off, depending on
{\tt mode}.

\item{\tt int (*DevQueryFrame) (VideoObject* theObject)}

Pointer to function that asks the player for the current address of the
medium.  Returns the address in terms of frames.

\item{\tt int (*DevQueryChapter) (VideoObject* theObject)}

Pointer to function that asks the player for the current chapter of the
medium.  Returns the chapter number.

\item{\tt int (*DevQueryAudio) (VideoObject* theObject)}

Pointer to function that asks the player for status of audio output.
Returns audio status.

\item{\tt int (*DevQueryVideo) (VideoObject* theObject)}

Pointer to function that asks the player for status of video output.
Returns video status.

\item{\tt int (*DevQueryMedium) (VideoObject* theObject, char* result)}

Pointer to function that asks the player for medium ID, where the medium
is either a videotape or a videodisc.  Returns the medium ID if integer,
or if a string, returns medium ID in {\tt result}, and returns 0.

\item{\tt int (*DevQueryStatus) (VideoObject* theObject)}

Pointer to function that asks the player for its status, eg play, pause,
search, etc.

\item{\tt int (*DevPing) (VideoObject* theObject)}

Pointer to function that sends a command to the player that is
guaranteed to elicit some response from the player. It returns the
number of characters read.  This function is used only during the
installation of a driver, by the Video Library function {\tt
PlayerVerified()} so that the application can attempt to verify that if
the player is correctly selected.

The verification is not guaranteed to be foolproof, because a command
may be recognized by many different players.  The programmer can make
the Ping() function more intelligent by returning a positive number of
characters read only when the response corresponds to what the current
player will return.  This eliminates some cases of misidentification,
but is again not foolproof and it can be difficult to enumerate all
possible responses in the case of some drivers.


\item{\tt int (*DevRecord) (VideoObject* theObject)}

Pointer to function that begins normal recording on the player.  In
video terminology, this is known as "assemble edit".

\item{\tt int (*DevRecordFromTo) (VideoObject*~theObject,
                                  int~startAddress,\\
                                  int~endAddresss,\\
                                  int~speedInFramesPerSecond)}


Pointer to function that records a segment of video, from {\tt
startAddress} to {\tt endAddress}.  This function is used for insert
editing, and is currently used in 2 different ways:

\begin{enumerate}

\item{startAddress == NULL, endAddress == NULL}\\
Puts player into "Insert Edit" mode, allowing precise time-code recording
to occur.

\item{startAddress == 0, endAddress != 0}\\
Records from current position (no search) until {\tt endAddress} is
reached.

\end{enumerate}

Notes on DevRecordFromTo:

\begin{enumerate}
\item 
Although {\tt speedInFramesPerSecond} field is here, as with {\tt
DevPlayFromTo()}, it is unlikely that players will allow recording at
other than 1x speed.  This field is here to accommodate the
possibility of future devices that can record at other than normal
speed.

\item
To do insert editing from, for example, frame 100 to frame 500, use
the VideoObject by first calling {\tt
DevPlayFromTo(theObject,~100,~100,~0)}.  Next, call {\tt
DevRecordFromTo(theObject,~0,~0,~0)} to turn on the insert editing
function of the player.  Finally, call {\tt
DevRecordFromTo(theObject,~0,~500,~0)} to do the actual recording.

It was decided to separate the semantics of putting a deck into insert
edit mode from the semantics of actually doing the recording in order
to help achieve better synchronization between playback and record
decks.  Some devices suffer a long setup time when requested to be put
into insert edit mode; by separating the two functions, application
programmers can better schedule editing functions for synchronized use.

\item
To record a single frame of video (e.g., frame 100), call {\tt
DevRecordFromTo()} in this manner: {\tt
DevRecordFromTo(theObject,~100,~100,~30)}.

\end{enumerate}

\end{enumerate}


\subsection{Status Codes and Error Codes}
\label{StatusAndErrorCodes}

Almost all the functions above return a status code. These codes are
listed in {\tt PlayerStatus.h} so that the application program gets a
uniform status code for a particular condition across all the devices.

If you are writing code to support a new video device, please make sure
that you map whatever status codes your device returns into the common
status codes defined in {\tt PlayerStatus.h}.  That way, the application
programmer will only need to code for one set of status codes.

Sometimes, the device will return an error code.  If you are writing
code to support a new video device, you should write the function within
the driver that writes commands out to the serial line and waits for
acknowledgments from the serial line such that it always detects when an
error is returned.  It then should decode the error and either display
the appropriate error message, by calling {\tt DisplayError()} or take
the appropriate corrective measures. The error code should not be
returned to the application. Instead, use {\tt PlayerReturnError}.


\section{Writing an Application to use the Video Library}

This section explains how your application can use the Video Library.

\subsection{Using the Video Object Functions}

The application uses the generic Video Object functions to perform the
desired function for a particular object, by passing into these
generic functions a pointer to the instance of the particular video
object. The application must therefore obtain this pointer somehow.

The way the application does this is by calling {\tt DevInit()}, passing
in the name of the device to be controlled. {\tt DevInit()} will return
a pointer to an instance of the device.

It may be necessary for your application to control several devices at
a time; to do so you may repeatedly call the {\tt DevInit()} function
with the appropriate parameters as necessary to create as many video
device controllers as your application needs.  If any two use the same
serial port, then these two control the same physical device. If they
are set up with different serial ports (this can be done after {\tt
DevInit()} has set up the object, by calling {\tt SetSerialLine()}),
then they control different devices.

The actual function called depends on the video object passed to the
generic {\tt Dev<Function>} calls.


\subsection{Status codes}

In order that applications get a uniform status code for a particular
condition, some common status codes have been defined in {\tt
PlayerStatus.h} that will allow the application to check the status of
the player. However, not all devices will be able to return all status
codes.

The application program does not need to check for any error code from
the driver in any situation, since errors will be reported to the
application and displayed using {\tt DisplayError()}. However, the
application may check for the status of the device and anticipate if an
error will occur (by knowing what is permissible and what is not, for
example, the NEC PC-VCR cannot pause unless in playback mode), then take
steps to help avoid the error (using the above case as an example, the
application can set the NEC PC-VCR into playback mode before calling the
{\tt DevPause()} function).



\subsection{Additions to the Application's Makefile}

\begin{enumerate}

\item Include {\tt videoObjects.c} in {\tt SOURCES} or {\tt SOURCES.c}.

\item Define {\tt VideoObjectSourceDir} as the directory where the
Video Library files are stored.

\item Add {\tt \$(VideoObjectSourceDir)/VideoLib.a} to {\tt LDLIBS}
before the X library ({\tt -lX} or {\tt -lX11}).

\item Add {\tt -I\$(VideoObjectSourceDir)} to {\tt CPPFLAGS}.

{\bf Note: Remember to declare the 4 functions in {\tt videoObjects.c}
in your application.}
\end{enumerate}

\subsection{Changes to {\tt videoObjects.c}}

\begin{enumerate}

\item Include the header files of your application.

\item Modify {\tt DisplayError()} and {\tt DisplayChoice()} for the
application.

\end{enumerate}

Recompile!


\section{Adding New Drivers to Your Application}

This section is for programmers who wish to write their own serial
line drivers.  It explains the various files in the video library, and
sets out the steps to take when writing a new video object for the
library for use in an existing application.



\subsection{Files in the Video Library}
\label{VideoLibraryFiles}

The Video Library is made up of the following files. {\bf None} of them
should be changed, unless you {\bf really} know what you are doing.

\begin{itemize}

\item{\tt videoObj.c}

This file contains the core functions to :

\begin{enumerate}
\item Set up the video object for use by an application program.\\
{\tt VideoObject*~BuildVideoObject(VideoObject*~deviceType)} returns an
instance of a video object for a device of {\tt deviceType}.

\item Set the serial line for the device.  {\tt int
SetSerialLine(Config* configuration, char* newSerialPort)} returns a
file descriptor for the device set to {\tt configuration}.

\item Check if a particular function has been implemented for a
particular object.\\ {\tt
enum~Boolean~CheckImplemented(VideoObject*~anObject,~int~aFunction)}
returns either {\tt Yes} or {\tt No}, depending on whether {\tt
anObject} has {\tt aFunction} implemented or not.  {\tt aFunction} is
{\tt \#defined} in {\tt videoObj.h}.

This function is useful when an application program must decide when
to provide a function that is not common for a specific device.

\item Test if the player and serial port are correctly selected.
{\tt int PlayerVerified(VideoObject* theObject, char* serialPort)}
returns either {\tt 1} (player and port are OK), or {\tt -1} (either the
player or the serial port is wrong).

As this function uses the {\tt DevPing} function to verify the device
and {\tt DevPing} is not foolproof (see description of DevPing in
\ref{DefiningVideoObjectFunctions}), this test is not guaranteed to be
correct in all cases.

\item Direct the generic {\tt Dev<Function>} calls made to the correct 
{\tt <Function>} for the particular device:  {\tt int
Dev<Function>(VideoObject* theObject, <OtherParameters>)}

\item Perform default {\tt <Function>} for non-implemented {\tt
Dev<Function>} calls.\\ {\tt
int~Default<Function>(VideoObject*~theObject,~<OtherParameters>)}

\item Get the maximum speed in frames per second that a device can play:

\begin{verbatim}
int GetDeviceMaxSpeed(VideoObject* theObject)
\end{verbatim}

\end{enumerate}


\item{\tt videoObj.h}

Header file for the Video Object, containing the relevant files,
declarations, data structures and data types.

\item{\tt PlayerStatus.h}

Header file for definitions of status codes returned by the device.

\item{Device Driver.c files}

These are files containing the code for controlling the devices
currently supported.

\item{Device Driver.h files}

These are the header files for the corresponding Driver files,
containing the declarations for the Video Object functions, and the
definitions for the error codes recognized by the particular driver.
Also, specific status codes for the device that is used {\bf only
internally} within the driver code can be specified here, in addition to
the status codes provided in {\tt PlayerStatus.h}.  These codes should
not clash with the codes defined in {\tt PlayerStatus.h}!

\item{Makefile}

A Makefile is supplied with the video library that compiles the
component drivers and builds a library out of it.

\end{itemize}


\subsection{Stub Files and Functions for Use by the Video Library}

The Video Library supplies a stub file that contains 4 stub functions to
aid the use of the Video Objects by the application programs, as well as
the configuration of each Video Object, and the structures of the Video
Objects.

The stub file is {\tt videoObjects.c}, and the 4 stub functions are:

\begin{enumerate}

\item{\tt VideoObject* DevInit(char* deviceName, char* serialPort)}\\
Matches {\tt deviceName} with the correct static variable defining the
appropriate videoObject, and returns a pointer to an instance of the
desired video object, by calling {\tt BuildVideoObject()}.  Then it
calls {\tt SetSerialLine()} to set the serial port to {\tt serialPort}.

\item{\tt void DisplayError(char* errorMsg1, char* errorMsg2)}\\
Takes the 2 strings returned by the driver that explains the error,
and displays it appropriately to the user. Application programs
should rewrite this function to best suit their needs.  Two strings
are provided in the case of long error messages.

\item{\tt void PrintDiagnostics(char* msg)}\\
If global enum Boolean variable {\tt diagMode} is {\tt Yes}, then the
diagnostic messages from the application and the drivers will be printed
(either to standard output, or wherever you might want to send the
messages). This is a useful feature, because the applications can hang
easily if the wrong messages were sent, or if there are timing problems,
and the diagnostics from the drivers would help identify the cause of
any device-related problems.

\item{\tt int DisplayChoice(char* msg1, char* msg2,\\
                     char* choiceMsg1, char* choiceMsg2)}\\
Takes the 2 strings returned by the driver that explains the choice to
be made, and displays it appropriately to the user.  The choice made is
returned as an integer. Application programs should rewrite this
function to best suit their needs.  Two strings are provided in the case
of long explanation messages.

\end{enumerate}

\subsection{Incorporating the New Video Object into the Video Library}

This section describes how to add a new video device to the Video
Library.

When you have written your own driver code and wish to add it to the
Video Library, do the following to add the driver to the library:

\begin{enumerate}

\item Add {\tt <DeviceName>Driver.c} and {\tt <DeviceName>Driver.h} to
{\tt SOURCES} in the Video Library's Makefile.

\item Add {\tt <DeviceName>Driver.o} to {\tt OBJECTS} in the Video
Library's Makefile.

\item Recompile the Video Library.

\end{enumerate}



\subsection{Incorporating the New Video Object into the Application}

This section describes how to add the new device supported into your own
application.  The changes to be made are all in {\tt videoObjects.c}.

\begin{enumerate}

\item Include the appropriate header file for your device. For example,
for the Pioneer4200 player:

\begin{verbatim}
        #include <Pioneer4200Driver.h>
\end{verbatim}

\item Add the configuration of your new object as a static variable,
named {\tt <modelName>Config}.  If you want to keep a copy of the
configuration as reference, copy the configuration as a {\bf comment} at
the end of {\tt videoObj.h}.

An example with the Pioneer4200 player: 

\begin{verbatim}
      static Config Pioneer4200Config =                      
      {
        "Pioneer4200",  
        "/dev/ttya",    
        4800,                   
        13,             
        8,
        Even,
        Yes,
        120,
        -1
        }
        ;
\end{verbatim}

\item Add the name of your device (as it is in the {\tt modelName}
field) into the {\tt allDevices} array and increment {\tt numDevices} by
1.

\item Write the video object for the device, naming the static variable
{\tt <modelName>Obj}. For the functions that are not implemented for
the device, put a {\tt NULL} in its place.

\item In function {\tt DevInit}, add another else-if statement to call
{\tt BuildVideoObject()} with {\tt \&<modelName>Obj} if {\tt deviceName}
matches {\tt <modelName>}.

\end{enumerate}

Naming convention: Name your driver code {\tt <DeviceName>Driver.c} and
its header file, {\tt <DeviceName>Driver.h}.  The device name should be
unique.



\subsection{Notes on Writing the Video Object}

\begin{itemize}

\item Implement each relevant video object function for the new video
device, following the description of what each function is supposed to
do in \ref{DefiningVideoObjectFunctions} above.

\item The functions in {\tt <DeviceName>Driver.c} that read and write
from the serial line should take care of error handling, and if error
display is necessary, should call {\tt DisplayError()} in {\tt
videoObjects.c} while still in {\tt <DeviceName>Driver.c}.  Do not
return error codes specific to each device back to the application
program.  These should only be used within {\tt <DeviceName>Driver.c} and
defined in {\tt <DeviceName>Driver.h}.

\item To aid tracking down of communication problems with the device,
the functions that send and receive commands from the serial line should
call {\tt PrintDiagnostics()} (implemented in {\tt videoObject.c}) with
descriptive messages about what is being sent and received, so that if
so desired, the user can see the communication between the device and
the computer.

\item Please use the status codes in {\tt PlayerStatus.h} when returning
from the Video Object functions. Do not use any other status codes that
you define yourself. If a status code is returned that is not in {\tt
PlayerStatus.h}, please pick the closest match.  Please see
\ref{StatusAndErrorCodes} above.

\item In {\tt <DeviceName>Driver.h}, include {\tt PlayerStatus.h} and
{\tt videoObj.h}.

\end{itemize}

Recompile!


\section{Enumerated Types}

The following enumerated types are defined in {\tt videoObj.h} and can
be freely used in any application using the Video Library.

\begin{verbatim}
        enum Parity {Odd, Even, Any};
        enum Boolean {No, Yes};
        enum Direction {Forward, Reverse};
\end{verbatim}


\appendix

\section{ASCII value table}
\label{ASCIITable}

ASCII value table (Decimal) - Character
\begin{verbatim}
     |  0 NUL|  1 SOH|  2 STX|  3 ETX|  4 EOT|  5 ENQ|  6 ACK|  7 BEL|
     |  8 BS |  9 HT | 10 NL | 11 VT | 12 NP | 13 CR | 14 SO | 15 SI |
     | 16 DLE| 17 DC1| 18 DC2| 19 DC3| 20 DC4| 21 NAK| 22 SYN| 23 ETB|
     | 24 CAN| 25 EM | 26 SUB| 27 ESC| 28 FS | 29 GS | 30 RS | 31 US |
     | 32 SP | 33  ! | 34  " | 35  # | 36  $ | 37  % | 38  & | 39  ' |
     | 40  ( | 41  ) | 42  * | 43  + | 44  , | 45  - | 46  . | 47  / |
     | 48  0 | 49  1 | 50  2 | 51  3 | 52  4 | 53  5 | 54  6 | 55  7 |
     | 56  8 | 57  9 | 58  : | 59  ; | 60  < | 61  = | 62  > | 63  ? |
     | 64  @ | 65  A | 66  B | 67  C | 68  D | 69  E | 70  F | 71  G |
     | 72  H | 73  I | 74  J | 75  K | 76  L | 77  M | 78  N | 79  O |
     | 80  P | 81  Q | 82  R | 83  S | 84  T | 85  U | 86  V | 87  W |
     | 88  X | 89  Y | 90  Z | 91  [ | 92  \ | 93  ] | 94  ^ | 95  _ |
     | 96  ` | 97  a | 98  b | 99  c |100  d |101  e |102  f |103  g |
     |104  h |105  i |106  j |107  k |108  l |109  m |110  n |111  o |
     |112  p |113  q |114  r |115  s |116  t |117  u |118  v |119  w |
     |120  x |121  y |122  z |123  { |124  | |125  } |126  ~ |127 DEL|
\end{verbatim}

\end{document}

